package com.ktkj.init.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ktkj.init.constant.UserInfoConstant;
import com.ktkj.init.dto.UpdatePasswordForm;
import com.ktkj.init.dto.UserInfoCondition;
import com.ktkj.init.dto.UserInfoForm;
import com.ktkj.init.entity.PermissionInfo;
import com.ktkj.init.entity.RoleInfo;
import com.ktkj.init.entity.RolePermissionMapping;
import com.ktkj.init.entity.UserInfo;
import com.ktkj.init.entity.UserRoleMapping;
import com.ktkj.init.exception.BusinessException;
import com.ktkj.init.mapper.UserInfoMapper;
import com.ktkj.init.service.PermissionInfoService;
import com.ktkj.init.service.RoleInfoService;
import com.ktkj.init.service.RolePermissionMappingService;
import com.ktkj.init.service.UserInfoService;
import com.ktkj.init.service.UserRoleMappingService;
import com.ktkj.init.utils.SpringUtils;
import com.ktkj.init.vo.QueryResult;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author ktkj
 * @since 2021-12-31
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Resource
    private RoleInfoService roleInfoService;

    @Resource
    private PermissionInfoService permissionInfoService;

    @Resource
    private UserRoleMappingService userRoleMappingService;

    @Resource
    private RolePermissionMappingService rolePermissionMappingService;

    @Override
    public QueryResult<UserInfo> page(UserInfoCondition condition) {
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(condition.getUserName())) {
            wrapper.like("user_name", condition.getUserName().trim());
        }
        if (condition.getState() != null) {
            wrapper.eq("state", condition.getState());
        }
        wrapper.orderByDesc("create_date");

        List<UserInfo> resultData;
        long totalRecord;
        if (condition.getCurrent() != -1) {
            IPage<UserInfo> page = page(new Page<>(condition.getCurrent(), condition.getPageSize()), wrapper);
            resultData = page.getRecords();
            totalRecord = page.getTotal();
        } else {
            resultData = list(wrapper);
            totalRecord = resultData.size();
        }
        QueryResult<UserInfo> queryResult = new QueryResult<>();
        queryResult.setResultData(resultData);
        queryResult.setTotalRecord(totalRecord);
        return queryResult;
    }

    @Override
    @Transactional
    public UserInfo saveOrUpdate(UserInfoForm form) {
        UserInfo bean = null;
        String errorMsg = "保存失败，请联系管理员！";
        try {
            Long userId = this.getByUserId();
            UserInfo newUserInfo = this.getByUserName(form.getUserName().trim());
            String encryptionPassword = "";
            if (form.getId() != null) {
                bean = getById(form.getId());
                if (bean == null) {
                    errorMsg = "id错误，没有查询到对应数据！";
                    throw new BusinessException(BusinessException.BUSSINESS_EXCEPTION, errorMsg);
                }
                if (newUserInfo != null && !newUserInfo.getUserName().equals(bean.getUserName())) {
                    errorMsg = "用户姓名不能重复！";
                    throw new BusinessException(BusinessException.BUSSINESS_EXCEPTION, errorMsg);
                }
                bean.setUpdateId(userId);
                bean.setUpdateDate(new Date());
                encryptionPassword = bean.getPassword();
            } else {
                if (newUserInfo != null) {
                    errorMsg = "用户姓名不能重复！";
                    throw new BusinessException(BusinessException.BUSSINESS_EXCEPTION, errorMsg);
                }
                bean = new UserInfo();
                bean.setCreateId(userId);
                //盐
                String salt = new SecureRandomNumberGenerator().nextBytes().toHex();
                bean.setSalt(salt);
                //加密
                SimpleHash simpleHash = new SimpleHash(UserInfoConstant.HASH_ALGORITHM_NAME, form.getPassword().trim(), salt, UserInfoConstant.HASH_ITERATIONS);
                encryptionPassword = simpleHash.toString();
            }
            SpringUtils.copyPropertiesIgnoreNull(form, bean);
            bean.setPassword(encryptionPassword);
            saveOrUpdate(bean);

            //关联用户与角色
            if (StringUtils.isNotBlank(form.getRoleIds())) {
                //先删除用户对应的角色
                QueryWrapper<UserRoleMapping> wrapper = new QueryWrapper<>();
                wrapper.eq("user_id", bean.getId());
                userRoleMappingService.remove(wrapper);

                //再新增用户对应的角色
                List<Long> idList = Arrays.asList(form.getRoleIds().trim().split(",")).stream().map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
                List<UserRoleMapping> userRoleMappingList = Lists.newArrayList();
                for (int i = 0; i < idList.size(); i++) {
                    UserRoleMapping userRoleMapping = new UserRoleMapping(bean.getId(), idList.get(i));
                    userRoleMappingList.add(userRoleMapping);
                }
                userRoleMappingService.saveBatch(userRoleMappingList, 10);
            }
        } catch (Exception e) {
            log.error(errorMsg, e);
            throw new BusinessException(BusinessException.BUSSINESS_EXCEPTION, errorMsg);
        }
        return bean;
    }

    @Override
    @Transactional
    public void updatePassword(UpdatePasswordForm form) {
        UserInfo bean = getById(form.getId());
        if (bean == null) {
            throw new BusinessException(-1, "id错误，没有查询到对应数据！");
        }
        //判断旧密码是否正确
        SimpleHash simpleHash = new SimpleHash(UserInfoConstant.HASH_ALGORITHM_NAME, form.getOldPassword().trim(),
                bean.getSalt(), UserInfoConstant.HASH_ITERATIONS);
        String encryptionPassword = simpleHash.toString();
        if (!encryptionPassword.equals(bean.getPassword())) {
            throw new BusinessException(-1, "旧密码错误，请重新输入！");
        }
        //修改新密码
        SimpleHash simpleHashNew = new SimpleHash(UserInfoConstant.HASH_ALGORITHM_NAME, form.getNewPassword().trim(),
                bean.getSalt(), UserInfoConstant.HASH_ITERATIONS);
        String encryptionPasswordNew = simpleHashNew.toString();
        bean.setPassword(encryptionPasswordNew);
        saveOrUpdate(bean);
    }

    @Override
    public UserInfo getByUserName(String userName) {
        UserInfo bean = getOne(new QueryWrapper<UserInfo>()
                .lambda()
                .eq(UserInfo::getUserName, userName));
        if (bean != null) {
            List<UserRoleMapping> userRoleMappingList = userRoleMappingService.getByUserId(bean.getId());
            if (!CollectionUtils.isEmpty(userRoleMappingList)) {
                List<RoleInfo> roleList = Lists.newArrayList();
                for (UserRoleMapping userRoleMapping : userRoleMappingList) {
                    RoleInfo roleInfo = roleInfoService.getById(userRoleMapping.getRoleId());
                    List<RolePermissionMapping> rolePermissionMappingList = rolePermissionMappingService.getByRoleId(roleInfo.getId());
                    if (!CollectionUtils.isEmpty(rolePermissionMappingList)) {
                        List<PermissionInfo> permissionInfoList = Lists.newArrayList();
                        for (RolePermissionMapping rolePermissionMapping : rolePermissionMappingList) {
                            PermissionInfo permissionInfo = permissionInfoService.getById(rolePermissionMapping.getPermissionId());
                            permissionInfoList.add(permissionInfo);
                        }
                        roleInfo.setPermissionInfoList(permissionInfoList);
                        roleList.add(roleInfo);
                    }
                }
                bean.setRoleList(roleList);
            }
        }
        return bean;
    }

    @Override
    public Long getByUserId() {
        //获取当前登录人
        UserInfo userInfo = (UserInfo) SecurityUtils.getSubject().getPrincipal();
        return userInfo != null ? userInfo.getId() : null;
    }
}
